{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VoxelGrid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook we are going to learn about how to construct and visualize a grid of voxels from a point cloud."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyntcloud import PyntCloud"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We are going to **load** a 3D model of an ankylosaurus from the provided `examples/data.`\n",
    "\n",
    "You could load other point cloud in any of the supported [point cloud formats](http://pyntcloud.readthedocs.io/en/latest/io.html).\n",
    "\n",
    "You can learn more about reading and writing point clouds in the `examples/[io]` notebooks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PyntCloud\n",
       "34820 points with 6 scalar fields\n",
       "69636 faces in mesh\n",
       "0 kdtrees\n",
       "0 voxelgrids\n",
       "Centroid: 0.029972486197948456, 1.1250594854354858, 2.887650489807129\n",
       "Other attributes:"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "anky = PyntCloud.from_file(\"data/ankylosaurus_mesh.ply\")\n",
    "anky"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the description, we can see that this is a 3D mesh with 69636 faces. \n",
    "\n",
    "We can visualize the mesh as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "anky.plot(mesh=True, backend=\"threejs\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![mesh](data/images/structures-voxelgrid-1.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And convert it to a point cloud by sampling 200.000 random points from the surface.\n",
    "\n",
    "You cand learn more about hoy to convert a triangular mesh into a point cloud in the `examples/[sampling]` notebooks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "anky_cloud = anky.get_sample(\n",
    "    \"mesh_random\", n=200000, rgb=True, normals=True, as_PyntCloud=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can visualize the new point cloud:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "anky_cloud.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![anky_cloud](data/images/structures-voxelgrid-2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VoxelGrid creation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A `VoxelGrid` is a structure generated by subdividing the minimum bounding box of a point cloud into **voxels**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![voxelgrid](data/images/structures-voxelgrid-3.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can create a `VoxelGrid` from a `PyntCloud` using the `add_structure` with the `voxelgrid` identifier and some other optional arguments.\n",
    "\n",
    "By default, a 1x1x1 `VoxelGrid` will be created, which is not very usefull."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`pyntcloud` supports different methods for specifying how a `VoxelGrid` shold be created.\n",
    "\n",
    "You can indicate the number of voxels per axis that you want, the desired size per axis of each voxel or a combination of both.\n",
    "\n",
    "There are some examples bellow:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Regular VoxelGrid using number of voxels per axis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid_id = anky_cloud.add_structure(\"voxelgrid\", n_x=64, n_y=64, n_z=64)\n",
    "\n",
    "voxelgrid = anky_cloud.structures[voxelgrid_id]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid.plot(d=3, mode=\"density\", cmap=\"hsv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![64x64x64](data/images/structures-voxelgrid-4.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Irregular VoxelGrid using number of voxels per axis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid_id = anky_cloud.add_structure(\"voxelgrid\", n_x=8, n_y=16, n_z=32)\n",
    "\n",
    "voxelgrid = anky_cloud.structures[voxelgrid_id]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid.plot(d=3, mode=\"density\", cmap=\"hsv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![8x16x32](data/images/structures-voxelgrid-5.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Regular VoxelGrid using sizes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid_id = anky_cloud.add_structure(\n",
    "    \"voxelgrid\", size_x=0.15, size_y=0.15, size_z=0.15\n",
    ")\n",
    "\n",
    "voxelgrid = anky_cloud.structures[voxelgrid_id]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid.plot(d=3, mode=\"density\", cmap=\"hsv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![0.15x0.15x0.15](data/images/structures-voxelgrid-6.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Irregular VoxelGrid using sizes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid_id = anky_cloud.add_structure(\n",
    "    \"voxelgrid\", size_x=0.01, size_y=0.05, size_z=0.15\n",
    ")\n",
    "\n",
    "voxelgrid = anky_cloud.structures[voxelgrid_id]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid.plot(d=3, mode=\"density\", cmap=\"hsv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![0.01x0.05x0.15](data/images/structures-voxelgrid-7.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### VoxelGrid mixing number of voxels and sizes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that, for the same axis, **sizes** override the value of the number of voxels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid_id = anky_cloud.add_structure(\n",
    "    \"voxelgrid\",\n",
    "    n_x=32,\n",
    "    size_y=0.05,\n",
    "    # n_z gets overrided by size_z and it'll be ignored\n",
    "    n_z=2,\n",
    "    size_z=0.01,\n",
    ")\n",
    "\n",
    "voxelgrid = anky_cloud.structures[voxelgrid_id]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid.plot(d=3, mode=\"density\", cmap=\"hsv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![32x0.05x0.01](data/images/structures-voxelgrid-8.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### VoxelGrid with irregular bounding box"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By default, the bounding box of the voxelgrid will be adapted to make all sides of equal length. This option can be disabled as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid_id = anky_cloud.add_structure(\n",
    "    \"voxelgrid\", n_x=64, n_y=64, n_z=64, regular_bounding_box=False\n",
    ")\n",
    "\n",
    "voxelgrid = anky_cloud.structures[voxelgrid_id]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid.plot(d=3, mode=\"density\", cmap=\"hsv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![irregular bounding box](data/images/structures-voxelgrid-9.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the now the shape of the voxels is not equal for all axis, in constrast with the same construction without the regular_bounding_box argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.015778325498104095, 0.0053504230454564095, 0.0094350166618824]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VoxelGrid Information"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once you have constructed a `VoxelGrid`, you can access many information about the structure."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Bellow is the code to get the actual VoxelGrid instance once you have added it to a PyntCloud."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxelgrid_id = anky_cloud.add_structure(\"voxelgrid\", n_x=64, n_y=64, n_z=64)\n",
    "\n",
    "voxelgrid = anky_cloud.structures[voxelgrid_id]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Corresponding voxel per axis for each point in the point cloud"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([32, 15, 29, ..., 47, 37, 25], dtype=int64)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.voxel_x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([39, 36, 23, ..., 27, 23, 36], dtype=int64)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.voxel_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([17, 14, 30, ..., 36, 17, 21], dtype=int64)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.voxel_z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Unique voxel number for each point in the point cloud"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([133585,  63758, 120286, ..., 194276, 153041, 104725], dtype=int64)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.voxel_n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Number of voxels per axis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This might be usefull in case you use size arguments for constructing the structure"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[64, 64, 64]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.x_y_z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Total number of voxels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "262144"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.n_voxels"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Shape of the voxel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.015778325498104095, 0.015778325498104095, 0.015778325498104095]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Minimum and maximum coordinates of each voxel per axis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "min_max_x, min_max_y, min_max_z = voxelgrid.segments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.43055117, -0.41477285, -0.39899452, -0.38321619, -0.36743787,\n",
       "       -0.35165954, -0.33588122, -0.32010289, -0.30432457, -0.28854624,\n",
       "       -0.27276792, -0.25698959, -0.24121127, -0.22543294, -0.20965461,\n",
       "       -0.19387629, -0.17809796, -0.16231964, -0.14654131, -0.13076299,\n",
       "       -0.11498466, -0.09920634, -0.08342801, -0.06764968, -0.05187136,\n",
       "       -0.03609303, -0.02031471, -0.00453638,  0.01124194,  0.02702027,\n",
       "        0.04279859,  0.05857692,  0.07435524,  0.09013357,  0.1059119 ,\n",
       "        0.12169022,  0.13746855,  0.15324687,  0.1690252 ,  0.18480352,\n",
       "        0.20058185,  0.21636017,  0.2321385 ,  0.24791683,  0.26369515,\n",
       "        0.27947348,  0.2952518 ,  0.31103013,  0.32680845,  0.34258678,\n",
       "        0.3583651 ,  0.37414343,  0.38992175,  0.40570008,  0.42147841,\n",
       "        0.43725673,  0.45303506,  0.46881338,  0.48459171,  0.50037003,\n",
       "        0.51614836,  0.53192668,  0.54770501,  0.56348334,  0.57926166])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "min_max_x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Voxel Centers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.42266202,  0.622388  ,  2.4117832 ],\n",
       "       [-0.42266202,  0.622388  ,  2.4275615 ],\n",
       "       [-0.42266202,  0.622388  ,  2.4433398 ],\n",
       "       ...,\n",
       "       [ 0.5713725 ,  1.6164225 ,  3.374261  ],\n",
       "       [ 0.5713725 ,  1.6164225 ,  3.3900392 ],\n",
       "       [ 0.5713725 ,  1.6164225 ,  3.4058175 ]], dtype=float32)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.voxel_centers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VoxelGrid Methods"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### VoxelGrid.query"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can `query` the voxelgrid with an array of points in order to find out in which number of voxel those points\n",
    "would lie."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "some_points = np.array([[0.5, 0.5, 0.5], [0.1, 0.1, 2.3], [0.49, 0.49, 0.49]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([237568, 135168, 237568], dtype=int64)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "voxelgrid.query(some_points)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### VoxelGrid.get_feature_vector"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can get the 3D array representing the VoxelGrid using different modes."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### binary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `binary` mode will return a 3D array with 0s on empty voxels and 1s on voxels that have one point or more."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "binary_feature_vector = voxelgrid.get_feature_vector(mode=\"binary\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(64, 64, 64)"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binary_feature_vector.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can count the number of occupied voxels as follow:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4413.0"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "binary_feature_vector.sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Which should match the number of unique voxel identifiers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4413"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(np.unique(voxelgrid.voxel_n))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### density"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `density` mode will return a 3D array with a value normalized between 0 and 1 representing the percentage of points that each voxel contains."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "density_feature_vector = voxelgrid.get_feature_vector(mode=\"density\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(64, 64, 64)"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "density_feature_vector.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The density feature vector should sum to 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9999999999999999"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "density_feature_vector.sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### x_max, y_max, z_max"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `x_max`, `y_max`, `z_max` modes will return a 3D array indicating the maximum coordinate value inside a voxel, for the corresponding axis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_max_feature_vector = voxelgrid.get_feature_vector(mode=\"x_max\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(64, 64, 64)"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_max_feature_vector.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The maximum and minimum `x` value of all voxels should match the maximum and minimum `x` value of the point cloud."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.5792616605758667, 0.5792616605758667)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_max_feature_vector.max(), max(anky_cloud.points[\"x\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### x_mean, y_mean, z_mean"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `x_mean`, `y_mean`, `z_mean` modes will return a 3D array indicating the mean coordinate value inside a voxel, for the corresponding axis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\daavoo\\desktop\\pyntcloud\\pyntcloud\\structures\\voxelgrid.py:184: RuntimeWarning: invalid value encountered in true_divide\n",
      "  vector = np.nan_to_num(voxel_sum / voxel_count)\n"
     ]
    }
   ],
   "source": [
    "z_mean_feature_vector = voxelgrid.get_feature_vector(mode=\"z_mean\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(64, 64, 64)"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z_mean_feature_vector.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The maximum and minimum `z` value of all voxels should be bellow/above the maximum and minimum `z` values of the point cloud."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3.20985860824585, 3.210721015930176)"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z_mean_feature_vector.max(), max(anky_cloud.points[\"z\"])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
